﻿// Desktop window class, (c)2010 Knihovnik
// This file is licensed under GNU GPL license v2, see more at http://www.gnu.org/licenses/gpl-2.0.html
namespace vKapse.VirtualDesktop.Core
{

	#region Using

	using System;
	using System.Drawing;
	using System.Runtime.InteropServices;

	#endregion Using

	/// <summary>
	/// Class that represents a window of a desktop
	/// </summary>
	internal class DesktopWindow
	{

		#region Win32

		private const int SW_HIDE = 0;
		private const int SW_SHOW = 5;
		private const int SW_FORCEMINIMIZE = 11;
		private const int SW_RESTORE = 9;

		[DllImport("User32")]
		private static extern int ShowWindow(int hwnd, int nCmdShow);

		[DllImport("user32.dll")]
		[return: MarshalAs(UnmanagedType.Bool)]
		static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);

		private struct POINTAPI
		{
			public int x;
			public int y;
		}

		private struct RECT
		{
			public int left;
			public int top;
			public int right;
			public int bottom;
		}

		private struct WINDOWPLACEMENT
		{
			public int length;
			public int flags;
			public int showCmd;
			public POINTAPI ptMinPosition;
			public POINTAPI ptMaxPosition;
			public RECT rcNormalPosition;
		}

		#endregion Win32

		#region Members

		private Desktop m_desktop; // Desktop, that owns this window
		private IntPtr m_hWnd; // Pointer to the window
		private string m_name; // Name
		private string m_processName; // Name of process
		private Size m_size; // Size of window
		private Point m_location; // Location of window

		#endregion Members

		#region Constructor

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="processName"></param>
		/// <param name="hWnd">Pointer (handle) to the window</param>
		/// <param name="desktop">Instance of <see cref="Desktop"/> that owns this window</param>
		public DesktopWindow(string processName, IntPtr hWnd, Desktop desktop)
		{
			this.m_processName = processName;
			this.m_hWnd = hWnd;
			this.m_desktop = desktop;
			
			this.GetInfo();
		}

		#endregion Constructor

		#region Private Methods

		/// <summary>
		/// Method gets info about this window
		/// </summary>
		private void GetInfo()
		{
			WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
			placement.length = Marshal.SizeOf(placement);
			DesktopWindow.GetWindowPlacement(this.m_hWnd, ref placement);

			// Gets size of window (width,height)
			this.m_size = new Size(placement.rcNormalPosition.right - placement.rcNormalPosition.left,
				placement.rcNormalPosition.bottom - placement.rcNormalPosition.top);

			// Gets location
			this.m_location = new Point(placement.rcNormalPosition.left, placement.rcNormalPosition.top);
		}

		#endregion Private Methods

		#region Internal Methods

		/// <summary>
		/// Shows this process
		/// </summary>
		internal void Show()
		{
			DesktopWindow.ShowWindow(this.m_hWnd.ToInt32(), DesktopWindow.SW_SHOW);
			this.GetInfo();
		}

		/// <summary>
		/// Hides this process
		/// </summary>
		internal void Hide()
		{
			this.GetInfo();
			DesktopWindow.ShowWindow(this.m_hWnd.ToInt32(), DesktopWindow.SW_HIDE);
		}

		/// <summary>
		/// Checks if the windows was closed or hided
		/// </summary>
		/// <returns>If it was closed, returns False, otherwise True.</returns>
		internal bool CheckAlive()
		{
			return Desktop.WindowCondition(this.m_hWnd); // Still exists?
		}

		#endregion Internal Methods

		#region Properties

		/// <summary>
		/// Gets location of window
		/// </summary>
		internal Point Location
		{
			get
			{
				return this.m_location;
			}
		}

		/// <summary>
		/// Gets size of window
		/// </summary>
		internal Size Size
		{
			get
			{
				return this.m_size;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public string ProcessName
		{
			get
			{
				return this.m_processName;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public string Name
		{
			get 
			{
				return this.m_name;
			}
			set
			{
				this.m_name = value;
			}
		}

		#endregion Properties

		#region Override Methods

		public override int GetHashCode()
		{
			return this.m_name.GetHashCode();
		}

		public override bool Equals(object obj)
		{
			if (obj is string)
			{
				string value = obj.ToString();
				return (this.m_name == value);
			}
			if (obj is DesktopWindow)
			{
				return (((DesktopWindow)obj).m_name == this.m_name);
			}
			return base.Equals(obj);
		}

		#endregion

	}
}
